From 82e65c30b303bc1dc74c1f595b5dc31b2d5fed58 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Wed, 22 Oct 2014 20:32:40 +0200 Subject: [PATCH] Deprecate old build system and add rust build script as target --- src/cargo/core/manifest.rs | 51 +++++++++++++++----- src/cargo/ops/cargo_rustc/context.rs | 4 +- src/cargo/ops/cargo_rustc/mod.rs | 32 +++++++----- src/cargo/util/toml.rs | 50 ++++++++++++++++--- tests/test_cargo_compile_custom_build.rs | 25 ++++++++++ tests/test_cargo_compile_old_custom_build.rs | 6 ++- tests/tests.rs | 1 + 7 files changed, 133 insertions(+), 36 deletions(-) create mode 100644 tests/test_cargo_compile_custom_build.rs diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index bd9599279..666790746 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -16,7 +16,7 @@ pub struct Manifest { targets: Vec, target_dir: Path, doc_dir: Path, - build: Vec, + build: Vec, // TODO: deprecated, remove warnings: Vec, exclude: Vec, metadata: ManifestMetadata, @@ -59,7 +59,7 @@ pub struct SerializedManifest { targets: Vec, target_dir: String, doc_dir: String, - build: Option>, + build: Option>, // TODO: deprecated, remove } impl> Encodable for Manifest { @@ -73,6 +73,7 @@ impl> Encodable for Manifest { targets: self.targets.clone(), target_dir: self.target_dir.display().to_string(), doc_dir: self.doc_dir.display().to_string(), + // TODO: deprecated, remove build: if self.build.len() == 0 { None } else { Some(self.build.clone()) }, }.encode(s) } @@ -131,8 +132,9 @@ pub struct Profile { doctest: bool, doc: bool, dest: Option, - plugin: bool, + for_host: bool, harness: bool, // whether to use the test harness (--test) + custom_build: bool, } impl Profile { @@ -146,8 +148,9 @@ impl Profile { test: false, doc: false, dest: None, - plugin: false, + for_host: false, doctest: false, + custom_build: false, harness: true, } } @@ -219,8 +222,13 @@ impl Profile { self.doctest } - pub fn is_plugin(&self) -> bool { - self.plugin + pub fn is_custom_build(&self) -> bool { + self.custom_build + } + + /// Returns true if the target must be built for the host instead of the target. + pub fn is_for_host(&self) -> bool { + self.for_host } pub fn get_opt_level(&self) -> uint { @@ -282,8 +290,9 @@ impl Profile { self } - pub fn plugin(mut self, plugin: bool) -> Profile { - self.plugin = plugin; + /// Sets whether the `Target` must be compiled for the host instead of the target platform. + pub fn for_host(mut self, for_host: bool) -> Profile { + self.for_host = for_host; self } @@ -291,6 +300,12 @@ impl Profile { self.harness = harness; self } + + /// Sets whether the `Target` is a custom build script. + pub fn custom_build(mut self, custom_build: bool) -> Profile { + self.custom_build = custom_build; + self + } } impl hash::Hash for Profile { @@ -302,7 +317,7 @@ impl hash::Hash for Profile { codegen_units, debug, rpath, - plugin, + for_host, ref dest, harness, @@ -313,8 +328,10 @@ impl hash::Hash for Profile { env: _, test: _, doctest: _, + + custom_build: _, } = *self; - (opt_level, codegen_units, debug, rpath, plugin, dest, harness).hash(into) + (opt_level, codegen_units, debug, rpath, for_host, dest, harness).hash(into) } } @@ -373,7 +390,7 @@ impl Manifest { targets: targets, target_dir: target_dir, doc_dir: doc_dir, - build: build, + build: build, // TODO: deprecated, remove warnings: Vec::new(), exclude: exclude, metadata: metadata, @@ -466,6 +483,18 @@ impl Target { } } + /// Builds a `Target` corresponding to the `build = "build.rs"` entry. + pub fn custom_build_target(name: &str, src_path: &Path, profile: &Profile, + metadata: Option) -> Target { + Target { + kind: BinTarget, + name: name.to_string(), + src_path: src_path.clone(), + profile: profile.clone(), + metadata: metadata, + } + } + pub fn example_target(name: &str, src_path: &Path, profile: &Profile) -> Target { Target { kind: ExampleTarget, diff --git a/src/cargo/ops/cargo_rustc/context.rs b/src/cargo/ops/cargo_rustc/context.rs index 0ea5dc8f8..7192aab7d 100644 --- a/src/cargo/ops/cargo_rustc/context.rs +++ b/src/cargo/ops/cargo_rustc/context.rs @@ -145,7 +145,7 @@ impl<'a, 'b: 'a> Context<'a, 'b> { if !visiting.insert(pkg.get_package_id()) { return } let key = (pkg.get_package_id(), target.get_name()); - let req = if target.get_profile().is_plugin() {PlatformPlugin} else {req}; + let req = if target.get_profile().is_for_host() {PlatformPlugin} else {req}; match self.requirements.entry(key) { Occupied(mut entry) => { *entry.get_mut() = entry.get().combine(req); } Vacant(entry) => { entry.set(req); } @@ -207,7 +207,7 @@ impl<'a, 'b: 'a> Context<'a, 'b> { ret.push(format!("{}{}", stem, self.target_exe)); } else { if target.is_dylib() { - let plugin = target.get_profile().is_plugin(); + let plugin = target.get_profile().is_for_host(); let kind = if plugin {KindPlugin} else {KindTarget}; let (prefix, suffix) = try!(self.dylib(kind)); ret.push(format!("{}{}{}", prefix, stem, suffix)); diff --git a/src/cargo/ops/cargo_rustc/mod.rs b/src/cargo/ops/cargo_rustc/mod.rs index 146b9d861..51d0644cf 100644 --- a/src/cargo/ops/cargo_rustc/mod.rs +++ b/src/cargo/ops/cargo_rustc/mod.rs @@ -153,11 +153,11 @@ fn compile<'a, 'b>(targets: &[&'a Target], pkg: &'a Package, } jobs.enqueue(pkg, jq::StageStart, init); - // First part of the build step of a target is to execute all of the custom - // build commands. + // Old custom build system + // TODO: deprecated, remove let mut build_cmds = Vec::new(); for (i, build_cmd) in pkg.get_manifest().get_build().iter().enumerate() { - let work = try!(compile_custom(pkg, build_cmd.as_slice(), cx, i == 0)); + let work = try!(compile_custom_old(pkg, build_cmd.as_slice(), cx, i == 0)); build_cmds.push(work); } let (freshness, dirty, fresh) = @@ -179,7 +179,8 @@ fn compile<'a, 'b>(targets: &[&'a Target], pkg: &'a Package, // // Each target has its own concept of freshness to ensure incremental // rebuilds on the *target* granularity, not the *package* granularity. - let (mut libs, mut bins, mut tests) = (Vec::new(), Vec::new(), Vec::new()); + let (mut builds, mut libs, mut bins, mut tests) = (Vec::new(), Vec::new(), + Vec::new(), Vec::new()); for &target in targets.iter() { let work = if target.get_profile().is_doc() { let (rustdoc, desc) = try!(rustdoc(pkg, target, cx)); @@ -189,11 +190,14 @@ fn compile<'a, 'b>(targets: &[&'a Target], pkg: &'a Package, try!(rustc(pkg, target, cx, req)) }; - let dst = match (target.is_lib(), target.get_profile().is_test()) { - (_, true) => &mut tests, - (true, _) => &mut libs, - (false, false) if target.get_profile().get_env() == "test" => &mut tests, - (false, false) => &mut bins, + let dst = match (target.is_lib(), + target.get_profile().is_test(), + target.get_profile().is_custom_build()) { + (_, _, true) => &mut builds, + (_, true, _) => &mut tests, + (true, _, _) => &mut libs, + (false, false, _) if target.get_profile().get_env() == "test" => &mut tests, + (false, false, _) => &mut bins, }; for (work, kind, desc) in work.into_iter() { let (freshness, dirty, fresh) = @@ -203,14 +207,16 @@ fn compile<'a, 'b>(targets: &[&'a Target], pkg: &'a Package, dst.push((job(dirty, fresh, desc), freshness)); } } + jobs.enqueue(pkg, jq::StageCustomBuild, builds); jobs.enqueue(pkg, jq::StageLibraries, libs); jobs.enqueue(pkg, jq::StageBinaries, bins); jobs.enqueue(pkg, jq::StageTests, tests); Ok(()) } -fn compile_custom(pkg: &Package, cmd: &str, - cx: &Context, first: bool) -> CargoResult { +// TODO: deprecated, remove +fn compile_custom_old(pkg: &Package, cmd: &str, + cx: &Context, first: bool) -> CargoResult { let root = cx.get_package(cx.resolve.root()); let profile = root.get_manifest().get_targets().iter() .find(|target| target.get_profile().get_env() == cx.env()) @@ -533,7 +539,7 @@ fn build_deps_args(mut cmd: ProcessBuilder, target: &Target, package: &Package, // target directory (hence the || here). let layout = cx.layout(pkg, match kind { KindPlugin => KindPlugin, - KindTarget if target.get_profile().is_plugin() => KindPlugin, + KindTarget if target.get_profile().is_for_host() => KindPlugin, KindTarget => KindTarget, }); @@ -562,7 +568,7 @@ pub fn process(cmd: T, pkg: &Package, // or their dependencies let mut native_search_paths = HashSet::new(); for &(dep, target) in cx.dep_targets(pkg).iter() { - if !target.get_profile().is_plugin() { continue } + if !target.get_profile().is_for_host() { continue } each_dep(dep, cx, |dep| { if dep.get_manifest().get_build().len() > 0 { native_search_paths.insert(layout.native(dep)); diff --git a/src/cargo/util/toml.rs b/src/cargo/util/toml.rs index f92d498ce..01d3beb5d 100644 --- a/src/cargo/util/toml.rs +++ b/src/cargo/util/toml.rs @@ -251,7 +251,7 @@ pub struct TomlProject { name: String, version: TomlVersion, authors: Vec, - build: Option, + build: Option, // TODO: `String` instead exclude: Option>, // package metadata @@ -264,6 +264,7 @@ pub struct TomlProject { repository: Option, } +// TODO: deprecated, remove #[deriving(Decodable)] pub enum TomlBuildCommandsList { SingleBuildCommand(String), @@ -440,10 +441,24 @@ impl TomlManifest { self.bench.as_ref().unwrap().iter().map(|t| t.clone()).collect() }; + // processing the custom build script + let (new_build, old_build) = match project.build { + Some(SingleBuildCommand(ref cmd)) => { + if cmd.as_slice().ends_with(".rs") && layout.root.join(cmd.as_slice()).exists() { + (Some(Path::new(cmd.as_slice())), Vec::new()) + } else { + (None, vec!(cmd.clone())) + } + }, + Some(MultipleBuildCommands(ref cmd)) => (None, cmd.clone()), + None => (None, Vec::new()) + }; + // Get targets let profiles = self.profile.clone().unwrap_or(Default::default()); let targets = normalize(lib.as_slice(), bins.as_slice(), + new_build, examples.as_slice(), tests.as_slice(), benches.as_slice(), @@ -476,13 +491,10 @@ impl TomlManifest { } } - let build = match project.build { - Some(SingleBuildCommand(ref cmd)) => vec!(cmd.clone()), - Some(MultipleBuildCommands(ref cmd)) => cmd.clone(), - None => Vec::new() - }; let exclude = project.exclude.clone().unwrap_or(Vec::new()); + let has_old_build = old_build.len() >= 1; + let summary = try!(Summary::new(pkgid, deps, self.features.clone() .unwrap_or(HashMap::new()))); @@ -500,13 +512,16 @@ impl TomlManifest { targets, layout.root.join("target"), layout.root.join("doc"), - build, + old_build, exclude, metadata); if used_deprecated_lib { manifest.add_warning(format!("the [[lib]] section has been \ deprecated in favor of [lib]")); } + if has_old_build { + manifest.add_warning(format!("warning: the old build command has been deprecated")); + } Ok((manifest, nested_paths)) } } @@ -623,6 +638,7 @@ impl fmt::Show for TomlPathValue { fn normalize(libs: &[TomlLibTarget], bins: &[TomlBinTarget], + custom_build: Option, examples: &[TomlExampleTarget], tests: &[TomlTestTarget], benches: &[TomlBenchTarget], @@ -689,7 +705,7 @@ fn normalize(libs: &[TomlLibTarget], } if target.plugin == Some(true) { - ret = ret.into_iter().map(|p| p.plugin(true)).collect(); + ret = ret.into_iter().map(|p| p.for_host(true)).collect(); } ret @@ -747,6 +763,21 @@ fn normalize(libs: &[TomlLibTarget], } } + fn custom_build_target(dst: &mut Vec, cmd: &Path, + profiles: &TomlProfiles) { + let profiles = [ + merge(Profile::default_dev().for_host(true), &profiles.dev), + merge(Profile::default_release().for_host(true), &profiles.release), + ]; + + let name = format!("build-script-{}", cmd.filestem_str().unwrap_or("")); + + for profile in profiles.iter() { + dst.push(Target::custom_build_target(name.as_slice(), + cmd, profile, None)); + } + } + fn example_targets(dst: &mut Vec, examples: &[TomlExampleTarget], profiles: &TomlProfiles, default: |&TomlExampleTarget| -> String) { @@ -829,6 +860,9 @@ fn normalize(libs: &[TomlLibTarget], ([], []) => () } + if let Some(custom_build) = custom_build { + custom_build_target(&mut ret, &custom_build, profiles); + } example_targets(&mut ret, examples, profiles, |ex| format!("examples/{}.rs", ex.name)); diff --git a/tests/test_cargo_compile_custom_build.rs b/tests/test_cargo_compile_custom_build.rs new file mode 100644 index 000000000..0853d9dc1 --- /dev/null +++ b/tests/test_cargo_compile_custom_build.rs @@ -0,0 +1,25 @@ +use support::{project, execs}; +use hamcrest::{assert_that}; + +fn setup() { +} + +test!(custom_build_compiled { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + + name = "foo" + version = "0.5.0" + authors = ["wycats@example.com"] + build = 'build.rs' + "#) + .file("src/main.rs", r#" + fn main() {} + "#) + .file("build.rs", r#" + invalid rust file, should trigger a build error + "#); + assert_that(p.cargo_process("build"), + execs().with_status(101)); +}) diff --git a/tests/test_cargo_compile_old_custom_build.rs b/tests/test_cargo_compile_old_custom_build.rs index e48986fc6..321dd8167 100644 --- a/tests/test_cargo_compile_old_custom_build.rs +++ b/tests/test_cargo_compile_old_custom_build.rs @@ -44,7 +44,7 @@ test!(old_custom_build { execs().with_status(0) .with_stdout(format!(" Compiling foo v0.5.0 ({})\n", p.url())) - .with_stderr("")); + .with_stderr("warning: the old build command has been deprecated")); }) test!(old_custom_multiple_build { @@ -108,7 +108,7 @@ test!(old_custom_multiple_build { execs().with_status(0) .with_stdout(format!(" Compiling foo v0.5.0 ({})\n", p.url())) - .with_stderr("")); + .with_stderr("warning: the old build command has been deprecated")); }) test!(old_custom_build_failure { @@ -148,6 +148,7 @@ test!(old_custom_build_failure { "#); assert_that(p.cargo_process("build"), execs().with_status(101).with_stderr(format!("\ +warning: the old build command has been deprecated\n\ Failed to run custom build command for `foo v0.5.0 ({dir}) Process didn't exit successfully: `{}` (status=101)\n\ --- stderr\n\ @@ -211,6 +212,7 @@ test!(old_custom_second_build_failure { "#); assert_that(p.cargo_process("build"), execs().with_status(101).with_stderr(format!("\ +warning: the old build command has been deprecated\n\ Failed to run custom build command for `foo v0.5.0 ({dir}) Process didn't exit successfully: `{}` (status=101)\n\ --- stderr\n\ diff --git a/tests/tests.rs b/tests/tests.rs index 49ed62565..0c0a47851 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -29,6 +29,7 @@ mod test_cargo; mod test_cargo_bench; mod test_cargo_clean; mod test_cargo_compile; +mod test_cargo_compile_custom_build; mod test_cargo_compile_old_custom_build; mod test_cargo_compile_git_deps; mod test_cargo_compile_path_deps; -- 2.30.2